package wiki.kaizen.cloud.shiro.stateless.util;

import io.jsonwebtoken.*;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.shiro.util.StringUtils;
import wiki.kaizen.cloud.shiro.stateless.properties.SecurityProperties;
import wiki.kaizen.cloud.shiro.stateless.shiro.AuthService;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * jwt 工具类
 * @author xeepoo
 * */
public class JWTUtil {

    public static final String ROLES_KEY = "roles";

    public static final String PERMS_KEY = "perms";

    private static String secret;

    private static String issuer;
    //过期时间
    private static  long expireTime;

    private static String algorithm;

    private static AuthService authService;

    public static void setProperties(SecurityProperties properties, AuthService auth) {
        secret = properties.getSecret();
        issuer = properties.getIssuer();
        expireTime = properties.getExpireTime();
        algorithm = properties.getTokenSignatureAlgorithm();
        authService = auth;

    }

    /**
     * 用户登录成功后生成Jwt
     * 使用Hs256算法  私匙使用用户密码
     */
    public static Token createJWT(String userCode) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.forName(algorithm);
        //生成JWT的时间
        long nowMillis = System.currentTimeMillis();
        Date date = new Date(nowMillis);
        String uid = ISecurityUtil.uid();

        String  audience = String.format(
            "%04d",new Random().nextInt(9999)
        );
        JwtBuilder tokenBuilder = Jwts.builder()
            .setId(audience + uid)
            .setIssuer(issuer)
            .setSubject(userCode)
            .setIssuedAt(date)
            .setAudience(audience)
            .signWith(signatureAlgorithm,secret)
            //设置过期时间
            .setExpiration(new Date(nowMillis+expireTime));

        AuthService.AuthInfo authInfo = authService.get(userCode);
        /*设置角色及角色权限*/
        List<String> roles = authInfo.getRoles();
        if(roles != null&& !roles.isEmpty()){
            tokenBuilder.claim(
                JWTUtil.ROLES_KEY,StringUtils.join(
                    roles.iterator(),","
                )
            );
        }
        List<String> perms = authInfo.getPerms();
        if(perms != null&& !perms.isEmpty()){
            tokenBuilder.claim(
                JWTUtil.PERMS_KEY,
                StringUtils.join(
                    perms.iterator(),","
                )
            );
        }


        JwtBuilder refreshTokenBuilder = Jwts.builder()
            .setId(uid)
            .setIssuedAt(date)
            .setSubject(userCode)
            .signWith(signatureAlgorithm, secret);

        return new Token(
                tokenBuilder.compact()
            )
            .setRefreshToken(
                new Token(refreshTokenBuilder.compact())
            );
    }


    /**
     * Token的解密
     * @param token 加密后的token
     */
    public static  Claims parseJWT(String token) {
        //得到DefaultJwtParser
        return Jwts.parser()
            //设置签名的秘钥
            .setSigningKey(secret)
            //设置需要解析的jwt
            .parseClaimsJws(token).getBody();

    }

    @Setter
    @Getter
    @Accessors(chain = true)
    public static class Token implements Serializable {
        public Token(){
        }
        public Token(String token){
            this.token = token;
        }
        private String token;
        private Token refreshToken;
    }
}
